package com.yuntsg.nnsfcp.controller.front;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yuntsg.nnsfcp.common.beans.ResultBean;
import com.yuntsg.nnsfcp.common.utils.CheckUtil;
import com.yuntsg.nnsfcp.common.utils.StringUtil;
import com.yuntsg.nnsfcp.front.entity.UserInfo;
import com.yuntsg.nnsfcp.front.mapper.UserInfoMapper;
import com.yuntsg.nnsfcp.service.front.CheckService;
import com.yuntsg.nnsfcp.service.front.impl.SendCodeLogServiceImpl;
import com.yuntsg.nnsfcp.service.front.ut.BCryptPasswordEncoder;
import com.yuntsg.nnsfcp.service.front.ut.MsgUtil;
import com.yuntsg.nnsfcp.common.utils.RedisUtil;
import com.yuntsg.nnsfcp.util.SmallTool;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 注册控制器
 *
 * @author ：ljx
 * @date ：Created in 2019/9/18
 */
//@Api(value = "前台用户注册", description = "(前台)用户注册")
@Slf4j
@RestController
@RequestMapping("register")
public class RegisterController {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private CheckService checkService;


    @Resource
    private SendCodeLogServiceImpl sendCodeLogService;


    /**
     * 用户注册, 保存注册用户信息
     *
     * @param userInfo 用户信息
     * @return
     */
    @PostMapping("register_user")
//    @ApiOperation(value = "用户注册", notes = "用户注册")
    public ResultBean<Object> registerUser(HttpServletRequest request, @RequestBody UserInfo userInfo) {
        CheckUtil.check(StringUtils.isNotEmpty(userInfo.getAccount()), "用户名不能为空");
        CheckUtil.check(StringUtils.isNotEmpty(userInfo.getPhone()), "手机号不能为空");
        CheckUtil.check(StringUtils.isNotEmpty(userInfo.getCode()), "请填写手机验证码");
        CheckUtil.check(StringUtils.isNotEmpty(userInfo.getPassword()), "请输入密码");
        CheckUtil.check(userInfo.getPassword().length() >= 6, "密码过于简单");

        //账号
        String account = userInfo.getAccount();
        //手机号
        String phone = userInfo.getPhone();
        //验证码
        String code = userInfo.getCode();
        //密码
        String password = userInfo.getPassword();


        //判断验证码
        boolean boo = checkCode(phone, code);
        request.getSession().removeAttribute("imgCode");
        RedisUtil.delString(phone);

        CheckUtil.check(boo, "验证码错误或已使用");

        // 判断重复 保存用户注册信息.
        try {
            boolean accountBoo = checkService.checkAccountReg(account);
            CheckUtil.check(accountBoo, "账号重复注册");
            boolean phoneBoo = checkService.checkPhoneReg(phone);
            CheckUtil.check(phoneBoo, "手机号重复注册");

            //获取ip判断是否属于校内 // true 校内, false 校外
//            if (ipBoo) {
//                if (school) {
//                    //是校内, 判断账户是否合法
//                    boolean b = checkAccountLength(account);
//                    CheckUtil.check(b, "请核对您的人事编号是否正确");
//                }
//            }

            UserInfo user = new UserInfo();
            user.setAccount(account);
            password = new BCryptPasswordEncoder().encode(password);
            user.setPassword(password);
            user.setPhone(phone);
            user.setName(account);
            user.setIsDelete(0);
            // 2024年2月21日09:23:44 插入之前校验如果多个直接忽略
            List<UserInfo> phone1 = userInfoMapper.selectList(new QueryWrapper<UserInfo>().eq("phone", user.getPhone()));
            if (phone1.size() == 0) {
                return new ResultBean<>(userInfoMapper.insert(user));
            } else {
                return new ResultBean<>();
            }
        } catch (Exception e) {
            CheckUtil.check(false, "重复注册");
            return new ResultBean<>();
        }
    }

    /**
     * 获取短信验证码
     *
     * @param phone 手机号
     * @return
     */
    @PostMapping("send_code")
//    @ApiOperation(value = "发送验证码", notes = "发送验证码")
    public ResultBean<Object> sendCode(HttpServletRequest request, String phone) {
        CheckUtil.check(StringUtils.isNotEmpty(phone), "手机号不能为空");

        boolean sendSwitch = false;
        Integer type = null;
        boolean boo = checkService.checkIsPhone(phone);
        CheckUtil.check(boo, "请输入正确的手机号码");
        //判断是不是在 注册页面
        String requestUrl = request.getHeader("Referer");
        log.info("requestUrl:{}", requestUrl);
        sendSwitch = true;
        type = 1;
//        if (StringUtils.isNotEmpty(requestUrl)) {
//            //判断是不是在注册页
        log.info("注册页发送短信");
        UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("phone", phone)
                .eq("is_delete", 0));
        CheckUtil.check(userInfo == null, "手机号已被注册");

//
//            //判断是不是在登陆页
//            if (requestUrl.contains("login")) {
//                log.info("登陆页发送短信");
//                UserInfo sendUserInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
//                        .eq("phone", phone).eq("is_delete", 0));
//                CheckUtil.notNull(sendUserInfo, "手机号码未注册");
//                sendSwitch = true;
//                type = 2;
//            }
//            if (requestUrl.contains("ocalhost")) {
//                sendSwitch = true;
//                type = 1;
//            }
//
//            //判断段是不是在用户信息修改页
//            if (requestUrl.contains("info")) {
//                log.info("用户修改密码发送短信");
//
//                Object uidObj = request.getAttribute("frontUserId");
//                CheckUtil.notNull(uidObj, "请登录");
//                Integer userId = Integer.valueOf(uidObj + "");
//
//                UserInfo dbUserInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
//                        .eq("id", userId).eq("is_delete", 0));
//                String phone1 = dbUserInfo.getPhone();
//
//                UserInfo sendUserInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
//                        .eq("phone", phone).eq("is_delete", 0));
//                CheckUtil.check(sendUserInfo != null, "手机号码未注册本系统,请确认手机号码");
//                String phone2 = sendUserInfo.getPhone();
//                if (StringUtils.isEmpty(phone2)) {
//                    phone2 = "";
//                }
//                CheckUtil.check(phone1.equals(phone2), "当前手机号码不属于当前账户");
//                sendSwitch = true;
//                type = 3;
//            }
//        }

        if (!sendSwitch) {
            log.error("非法发送短信: " + phone);
        }
        CheckUtil.check(sendSwitch, "非法访问");

        //记录用户发短信的用途 次数, 及当日次数
        //时间格式存储为可切割类型, 以方便获取到当日用户发送的次数.
        boolean sendSwitch2 = sendCodeLogService.checkSendCode(phone, type);
        CheckUtil.check(sendSwitch2, "当日发送次数以达到限制");

        try {

            String code = null;

            if (type == 1) {
                //注册
                code = MsgUtil.generatorSms(phone, "");
            } else if (type == 2) {
                //短信登陆
                code = MsgUtil.generatorSms(phone, "");
            } else if (type == 3) {
                //修改密码
                code = MsgUtil.generatorSms(phone, "");
            }
            log.info("发送验证码是++" + code);


            //存入redis
            RedisUtil.setString(phone, code, 5);
            return new ResultBean<>("send successfully");
        } catch (Exception e) {
            log.error("用户注册验证码发送失败了");
            e.printStackTrace();
            CheckUtil.check(false, "验证码发送失败,请重新获取");
        }
        return new ResultBean<>();
    }


    /**
     * 校外用户找回密码发送短信
     *
     * @param phone 手机号
     * @return
     */
    @PostMapping("send_code_backpass")
//    @ApiOperation(value = "发送验证码 重置密码用的", notes = "发送验证码")
    public ResultBean<Object> sendCodeBackPass(String phone) {
        CheckUtil.check(StringUtils.isNotEmpty(phone), "手机号不能为空");
        boolean boo = checkService.checkIsPhone(phone);
        CheckUtil.check(boo, "请输入正确的手机号码");
        try {
            String code = null;
            code = MsgUtil.generatorSms(phone, "");
            log.info("重置密码发送的短信验证码是" + code);
            //存入redis
            RedisUtil.setString(phone, code, 5);
            return new ResultBean<>("send successfully");
        } catch (Exception e) {
            log.error("用户注册验证码发送失败了");
            e.printStackTrace();
            CheckUtil.check(false, "验证码发送失败,请重新获取");
        }
        return new ResultBean<>();
    }


    /**
     * 校外用户重置密码
     *
     * @param phone    手机号
     * @param password 密码
     * @return
     */
    @PostMapping("send_code_Resetpass")
//    @ApiOperation(value = "重置密码", notes = "重置密码")
//    @ApiImplicitParams({
//            @ApiImplicitParam(value = "手机号", name = "phone", required = true),
//            @ApiImplicitParam(value = "密码", name = "password", required = true),
//            @ApiImplicitParam(value = "短信验证码", name = "code", required = true)
//    })
    public ResultBean<Object> sendCodeBackPass(HttpServletRequest request, String phone, String password, String code) {

        log.info("手机号" + phone);
        log.info("密码" + password);
        log.info("短信验证码" + code);
        CheckUtil.check(StringUtils.isNotEmpty(phone), "手机号不能为空");
        CheckUtil.check(StringUtils.isNotEmpty(password), "密码不能为空");
        CheckUtil.check(StringUtils.isNotEmpty(code), "验证码不能为空");

        //判断验证码
        boolean boo = checkCode(phone, code);
        request.getSession().removeAttribute("imgCode");
        RedisUtil.delString(phone);

        CheckUtil.check(boo, "验证码错误或已使用");

        password = new BCryptPasswordEncoder().encode(password);

        UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("phone", phone));
        userInfo.setPassword(password);
        int i = userInfoMapper.updateById(userInfo);

        if (i != 1) {
            CheckUtil.check(false, "修改失败,请重试");
        }
        return new ResultBean<>();
    }


    /**
     * 检查账户 是否重复
     * 防止重复注册
     *
     * @param str 账户,手机号
     * @return
     */
    @GetMapping("check_account")
//    @ApiOperation(value = "重复注册校验", notes = "重复注册校验")
//    @ApiImplicitParam(name = "str", value = "账号")
    public ResultBean<Object> checkAccountExit(HttpServletRequest request, String str) {

        //查询账户
        UserInfo user = null;
//        String userIp = IPUtil2.getIpAddr(request);
//        SmallTool.printMess("输出一下ip地址" + userIp);
//        if (userIp.contains(",")) {
//            userIp = userIp.split(",")[0];
//        }
//        boolean school = ipService.isSchool(userIp);
//        if (school) {

        //判空
//            if (StringUtils.isEmpty(str)) {
//                CheckUtil.check(false, "请输入工号/学号");
//            }
//
//            //判断纯数字
//            boolean b = checkService.checkIsNum(str);
//            CheckUtil.check(b, "请使用纯数字工号/学号");
//
//            //判断长度
//            if (str.length() <= 0 || str.length() >= 20) {
//                CheckUtil.check(false, "输入的工号/学号长度有误");
//            }
//
//            //校内
//            user = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
//                    .eq("account", str).eq("is_delete", 0));
//            CheckUtil.check(user == null, "工号/学号已经被注册");

//        } else
        {

            if (StringUtils.isEmpty(str)) {
                CheckUtil.check(false, "请输入账号");
            }

            //判断账号长度
            if (str.length() < 6) {
                CheckUtil.check(false, "请核实输入长度账号必须大于6位");
            }

            if (str.length() > 16) {
                CheckUtil.check(false, "用户名长度不能超过16个字符");
            }

            //特殊字符判断
            boolean boo = checkService.checkSpecial(str);
            if (boo) {
                CheckUtil.check(false, "请勿使用特殊字符");
            }

            //校外
            //校验账户必须是 字母 加 数字
            boolean accountCheck = checkService.checkAbcAndNum(str);
            CheckUtil.check(accountCheck, "账号需字母加数字的组合");
            //判断账号有没有被注册
            user = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
                    .eq("account", str).eq("is_delete", 0));
            CheckUtil.check(user == null, "账号已经被注册");
        }
        user = null;
        return new ResultBean<>(true);
    }

    /**
     * 检查账户 是否重复
     * 防止重复注册
     *
     * @param str 账户,手机号
     * @return
     */
    @GetMapping("check_phoneexit")
//    @ApiOperation(value = "找回密码检测是不是已注册的", notes = "找回密码检测是不是已注册的")
//    @ApiImplicitParam(name = "str", value = "账号")
    public ResultBean<Object> checkAccount(HttpServletRequest request, String str) {

        CheckUtil.check(!StringUtil.isEmpty(str), "请输入手机号");
        UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("phone", str));
        if (userInfo == null) {
            CheckUtil.check(false, "校外用户请先注册");
        } else {
            if (userInfo.getIsDelete() == 1) {
                CheckUtil.check(false, "账户已被删除,请联系管理员");
            } else {
                return new ResultBean<>(true);
            }
        }
        return new ResultBean<>(true);
    }

    /**
     * 检查手机号码是否重复
     *
     * @param request 请求
     * @param str     手机号码
     * @return
     */
    @GetMapping("check_phone")
//    @ApiOperation(value = "重复注册校验", notes = "重复注册校验")
//    @ApiImplicitParam(name = "str", value = "手机号")
    public ResultBean<Object> checkPhone(HttpServletRequest request, String str) {
        log.info("开始校验验手机号");
        //避免 空值, 一直弹出提示.
        if (StringUtils.isEmpty(str)) {
            CheckUtil.check(false, "请输入手机号码");
        }

        //判断是否是数字
        boolean ifNum = checkService.checkIsNum(str);
        CheckUtil.check(ifNum, "请使用纯数字");

        //校验手机号
        boolean phoneLegal = checkService.checkIsPhone(str);
        //查询手机号码
        CheckUtil.check(phoneLegal, "手机号码有误");

        UserInfo user = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
                .eq("phone", str).eq("is_delete", 0));
        CheckUtil.check(user == null, "手机号已经被注册");
        user = null;
        return new ResultBean<>(true);
    }

    /**
     * 检查验证码是否正确
     *
     * @param phone   用户手机号码
     * @param smsCode 验证码
     */
    private boolean checkCode(String phone, String smsCode) {
        //判空
        if (phone == null || "".equals(phone) || smsCode == null || "".equals(smsCode)) {
            return false;
        }

        //通过手机号码到 redis 中获取验证码, 用于校验
        Object redisCodeObj = RedisUtil.getString(phone);
        if (redisCodeObj != null) {
            SmallTool.printMess("redis存在的手机++++" + phone + "验证码+++++" + redisCodeObj.toString());
        } else {
            return false;
        }
        if (redisCodeObj != null) {
            String redisCode = redisCodeObj + "";
            //判空
            if (StringUtils.isEmpty(redisCode)) {
                return false;
            }

            //比较是否一致
            if (!smsCode.equals(redisCode)) {
                return false;
            }
        } else {
            return false;
        }

        //清除存储在redis中的验证码
        RedisUtil.delString(phone);

        return true;
    }

    /**
     * 账户长度校验
     *
     * @param account 账号
     * @return
     */
    private boolean checkAccountLength(String account) {
        //判断是否为纯数字
        boolean ifNum = Pattern.matches("^[-\\+]?[\\d]*$", account);
        //判断长度
        boolean ifLength = account.length() >= 7;
        if (ifLength && ifNum) {
            return true;
        }
        return false;
    }

}
